package cn.com.zetatech.loader.common.ftp;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class FtpClient extends ConnectionClient {

    private org.apache.commons.net.ftp.FTPClient ftpClient;

    public FtpClient(String serverIP, int serverPort, String userName, String password) throws Exception {
        if (serverIP == null || serverPort < 0 || userName == null || userName.equals("")) {
            throw new Exception();
        }
        this.serverIP = serverIP;
        this.serverPort = serverPort;
        this.userName = userName;
        this.password = password;
        ftpClient = new FTPClient();

    }

    @Override
    public void login(int timeout) throws Exception {
        ftpClient.setConnectTimeout(timeout);
        ftpClient.setControlEncoding("UTF-8");
        if (!ftpClient.isConnected()) {
            ftpClient.connect(serverIP, serverPort);
            ftpClient.login(userName, password);
        }
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(org.apache.commons.net.ftp.FTPClient.BINARY_FILE_TYPE);
        log.info("FTP连接成功");
    }

    @Override
    public InputStream get(String filePath) throws Exception {
        return ftpClient.retrieveFileStream(filePath);
    }

    @Override
    public boolean remove(String filePath) throws Exception {
        return ftpClient.deleteFile(filePath);
    }

    @Override
    public boolean copy(String sourcePath, String targetDir, String fileName) throws Exception {
        boolean pathIsExist = ftpClient.changeWorkingDirectory(targetDir);
        if (!pathIsExist) {//不存在文件夹
            String[] dirs = targetDir.split("/");
            // 分层创建目录
            StringBuilder pathBuilder = new StringBuilder();
            for (String dir : dirs) {
                if (StringUtils.isNotBlank(dir)) {
                    pathBuilder.append("/").append(dir);
                    String path = pathBuilder.toString();
                    if (ftpClient.changeWorkingDirectory(path)) {
                        ftpClient.makeDirectory(path);
                        ftpClient.changeWorkingDirectory(path);
                    }
                }
            }
            ftpClient.changeWorkingDirectory(targetDir);
        }

        // 进入源文件所在目录
        String source = new String(sourcePath).substring(0, new String(sourcePath).lastIndexOf("/"));
        ftpClient.changeWorkingDirectory(source);
        // 使用被动模式获取文件
        String name = new String(sourcePath).substring(new String(sourcePath).lastIndexOf("/") + 1);
        java.io.InputStream is = ftpClient.retrieveFileStream(name);
        this.ftpClient.getReply();
        // 进入目标目录
        ftpClient.changeWorkingDirectory(targetDir);
        // 存储文件到目标目录
        boolean storeSuccess = ftpClient.storeFile(fileName, is);
        return storeSuccess;
    }

    @Override
    public boolean move(String sourcePath, String targetDir, String fileName) throws Exception {
        boolean pathIsExist = ftpClient.changeWorkingDirectory(targetDir);
        if (!pathIsExist) {//不存在文件夹
            String[] dirs = targetDir.split("/");
            // 分层创建目录
            StringBuilder pathBuilder = new StringBuilder();
            for (String dir : dirs) {
                if (StringUtils.isNotBlank(dir)) {
                    pathBuilder.append("/").append(dir);
                    String path = pathBuilder.toString();
                    if (ftpClient.changeWorkingDirectory(path)) {
                        ftpClient.makeDirectory(path);
                        ftpClient.changeWorkingDirectory(path);
                    }
                }
            }
        }
        return ftpClient.rename(sourcePath, targetDir + "/" + fileName);
    }

    @Override
    public Map<String,Long> listFileSize(String dir, List<String> fileNames) {
        Map<String, Long> fileSizes = new HashMap<>();
        try {
            boolean pathIsExist = ftpClient.changeWorkingDirectory(dir);
            if (!pathIsExist) {
                throw new Exception(String.format("ftp路径非法：%s", dir));
            }
            FTPFile[] ftpFiles = ftpClient.listFiles(dir, file -> file.isFile() && fileNames.contains(file.getName()));
            Map<String, Long> ftpFileAndSize = Arrays.stream(ftpFiles).collect(Collectors.toMap(FTPFile::getName, FTPFile::getSize));
            for (String fileName : fileNames) {
                fileSizes.put(fileName, ftpFileAndSize.getOrDefault(fileName, 0L));
            }
            return fileSizes;
        } catch (Exception e) {
            log.error("查询文件大小错误:{}", e.getMessage(), e);
        }
        return fileSizes;
    }

    @Override
    public void disconnect() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
                log.info("FTP连接断开");
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    @Override
    public boolean isConnected() {
        return ftpClient != null && ftpClient.isConnected();
    }

    @Override
    public void pendingReset() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.completePendingCommand();
            } catch (IOException e) {
                log.error("ftpClient pendingReset fail !", e);
            }
        }
    }
}
